package com.joinway.framework.extension.utils;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.regex.Pattern;

import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 数值工具类
 * @author liliang
 *
 */
public final class NumberUtils {
	
	private final static Logger log = LoggerFactory.getLogger(NumberUtils.class);
	
	private static final Pattern NUMBER_PATTERN = Pattern.compile("\\d+(\\.\\d+)?");
	
	/**
	 * 把任意对象转换为整数
	 * @param obj 目标对象
	 * @return 整数数值，如果不能转换返回0
	 */
	public static int convertToInt(Object obj){
		int value = 0;
		
		try{
			value = Integer.valueOf(String.valueOf(obj));
		}catch(NumberFormatException  e){
			log.warn(e.getMessage());
		}
		
		return value;
	}
	
	/**
	 * 把任意对象转换为短整数
	 * @param obj  目标对象
	 * @return 短整数数值，如果不能转换返回0
	 */
	public static short convertToShort(Object obj){
		short value = 0;
		
		try{
			value = Short.valueOf(String.valueOf(obj));
		}catch(NumberFormatException  e){
			log.warn(e.getMessage());
		}
		
		return value;
	}
	
	/**
	 * 把任意对象转换为浮点数
	 * @param obj  目标对象
	 * @return 浮点数数值，如果不能转换返回0
	 */
	public static float convertToFloat(Object obj){
		float value = 0;
		
		try{
			value = Float.valueOf(String.valueOf(obj));
		}catch(NumberFormatException  e){
			log.warn(e.getMessage());
		}
		
		return value;
	}
	
	/**
	 * 把任意对象转换为浮点数
	 * @param obj 目标对象
	 * @param scale 小数位数
	 * @return 浮点数数值，如果不能转换返回0
	 */
	public static float convertToFloat(Object obj, int scale){
		float value = 0;
		
		try{
			value = Float.valueOf(convertToNumber(obj, scale));
		}catch(NumberFormatException  e){
			log.warn(e.getMessage());
		}
		
		return value;
	}

	/**
	 * 把任意对象转换为数值字符串
	 * @param obj 目标对象
	 * @param scale 小数位数
	 * @return 字符串数值
	 */
	public static String convertToNumber(Object obj, int scale){
		String value = "0";
		
		try{
			BigDecimal bd = new BigDecimal(String.valueOf(obj));
			value = bd.setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
		}catch(NumberFormatException  e){
			log.warn(e.getMessage());
		}
		
		return value;
	}
	
	/**
	 * 把任意对象转换为数值字符串
	 * @param obj 目标对象
	 * @return 字符串数值
	 */
	public static String convertToNumber(Object obj){
		String value = "0";
		
		try{
			BigDecimal bd = new BigDecimal(String.valueOf(obj));
			value = bd.toString();
		}catch(NumberFormatException  e){
			log.warn(e.getMessage());
		}
		
		return value;
	}
	
	/**
	 * 把任意对象转换为双精度浮点数
	 * @param obj 目标对象
	 * @return 双精度浮点数数值，如果不能转换返回0
	 */
	public static double convertToDouble(Object obj){
		double value = 0;
		
		try{
			value = Double.valueOf(String.valueOf(obj));
		}catch(NumberFormatException  e){
			log.warn(e.getMessage());
		}
		
		return value;
	}
	
	/**
	 * 把任意对象转换为BigDecimal
	 * @param obj 目标对象
	 * @return 转换后数值，如果不能转换返回0
	 */
	public static BigDecimal convertToBigDecimal(Object obj){
		BigDecimal value = BigDecimal.ZERO;
		
		try{
			value = new BigDecimal(String.valueOf(obj));
		}catch(Exception e){
			log.warn(e.getMessage());
		}
		
		return value;
	}
	
	/**
	 * 对多个BigDecimal求和
	 * @param nums 目标数值列表
	 * @return 求和结果
	 */
	public static BigDecimal add(BigDecimal...nums){
		BigDecimal sum = BigDecimal.ZERO;
		
		if(ArrayUtils.isNotEmpty(nums)){
			for(BigDecimal n : nums){
				if(n != null){
					sum = sum.add(n);
				}
			}
		}
		
		return sum;
	}
	
	/**
	 * 判断对象是否可以转换为数字
	 * @param obj 目标对象
	 * @return true可以转换，false不能转换
	 */
	public static boolean isNumber(Object obj){
		if(obj instanceof Number){
			return true;
		}
		
		if(obj instanceof BigInteger || obj instanceof BigDecimal){
			return true;
		}
		
		return NUMBER_PATTERN.matcher(String.valueOf(obj)).matches();
	}
	
	/**
	 * 计算大于商值的最小整数，如5 / 3 = 2
	 * @param x 被除数
	 * @param y 除数
	 * @return 大于商值的最小整数
	 */
	public static int dividePlusMod(int x, int y){
		int v = Math.floorDiv(x, y);
		return v = v + (x % y > 0 ? 1 : 0);
	}
	
	private NumberUtils(){}
}

